package com.candy.service.impl;

import com.candy.dao.IAccountDao;
import com.candy.dao.impl.AccountDaoImpl;
import com.candy.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.Date;

/**
 * 使用xml方式进行配置：
 * <bean id="AccountService" class="com.candy.service.impl.AccountSerivceImpl" scope="prototype"
 * init-method="initMethod" destroy-method="endMethod">
 *       <property name="name" value="李逍遥"></property>
 * </bean>
 *
 * 注解有四种分类：
 * 1、进行对象创建：
 *        与xml配置中的bean标签的作用是一致的
 *        Component:
 *          作用：用于把当前类对象存入spring容器中
 *          属性：
 *       value：用于指定bean的id。当我们不写时，它的默认值是当前类名，且首字母改小写。
 *       @Controller	@Service	@Repository
 *      他们三个注解都是针对一个的衍生注解，他们的作用及属性都是一模一样的。他们只不过是提供了更加明确的语义化。
 *      @Controller：一般用于表现层的注解。
 *       @Service：一般用于业务层的注解。
 *      @Repository：一般用于持久层的注解。
 * 细节：如果注解中有且只有一个属性要赋值时，且名称是 value，value 在赋值是可以不写。
 *
 * 2、注入数据的：
 *       与xml配置中的property标签的作用是一致的
 * @Autowired
 * 用于注入数据的
 * 他们的作用就和在xml配置文件中的bean标签中写一个<property>标签的作用是一样的
 * Autowired:
 *     作用：自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配，就可以注入成功
 *           如果ioc容器中没有任何bean的类型和要注入的变量类型匹配，则报错。
 *           如果Ioc容器中有多个类型匹配时：
 *     出现位置：
 *         可以是变量上，也可以是方法上
 *     细节：
 *         在使用注解注入时，set方法就不是必须的了。
 *      Qualifier:
 *     作用：在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以（稍后我们讲）
 *     属性：
 *         value：用于指定注入bean的id。
 *      Resource
 *     作用：直接按照bean的id注入。它可以独立使用
 *     属性：
 *         name：用于指定bean的id。
 * 以上三个注入都只能注入其他bean类型的数据，而基本类型和String类型无法使用上述注解实现。
 * 另外，集合类型的注入只能通过XML来实现。
 * Value
 *     作用：用于注入基本类型和String类型的数据
 *     属性：
 *         value：用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式）
 *                 SpEL的写法：${表达式}
 *
 * 3、改变作用范围的：
 *        与xml配置中的scope属性的作用是一致的
 *       @Scope注解：
 *       作用：
 *         指定 bean 的作用范围。属性：
 *       value：指定范围的值。
 *              取值：singleton prototype request session globalsession
 *
 * 4、与声明周期相关的：
 *        与xml配置中的init-method、destroy-method的作用是一致的
 *          PreDestroy
 *          作用：用于指定销毁方法
 *      PostConstruct
 *          作用：用于指定初始化方法
 */
@Component(value = "AccountService")
@Scope(value = "singleton")
public class AccountSerivceImpl implements IAccountService {
    @Value("张三")
    private String name;
    private Integer age;
    private Date birthday;

//    @Autowired
//    @Qualifier(value = "accountDaoImpl")
//    @Resource(name = "accountDaoImpl")
    @Value("#{accountDaoImpl}")
    private IAccountDao accountDao;

    public AccountSerivceImpl() {
    }

    public AccountSerivceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }



    @Override
    public void saveAccount() {
        accountDao.saveAccount();
        System.out.println(name);

    }


    @PostConstruct
    public void  initMethod(){
        System.out.println("对象初始化调用");
    }
    @PreDestroy
    public void endMethod(){
        System.out.println("对象销毁时");
    }

    @Override
    public String toString() {
        return "AccountSerivceImpl{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }
}
